SECTION .data
invalid db "invalid", 0h
huanHang db 10,0h
sign db "here",0h

SECTION .bss
input_string: resb 255
first_string: resb 255
second_string: resb 255
first_num: resb 255
second_num: resb 255
third_num: resb 255
first_len: resb 255
second_len:resb 255
mid_result: resb 255
result: resb 255

SECTION .text
global main




;清除[eax]
clear:
    push ebx
    mov ebx, 0
.loop:
    cmp ebx, 255
    je .rett
    mov BYTE[eax], 0
    inc ebx
    inc eax
    jmp .loop
.rett:
    pop ebx
    ret

clearall:
    mov eax, input_string
    call clear
    mov eax, first_string
    call clear
    mov eax, second_string
    call clear
    mov eax, first_num
    call clear
    mov eax, second_num
    call clear
    mov eax, first_len
    call clear
    mov eax, second_len
    call clear
    mov eax, third_num
    call clear
    mov eax, mid_result
    call clear
    ret


;解析字符串，有限状态机，1）数字...数字...加减乘号...（加减乘号）...数字...数字...空格
;2)q
;3）其它非法
;将数字以字符串到形式存储到first_string, second_string中
;判断结果会输出进eax中，取值1,2,3,4,5(分别对应q,invalid,+,-,*）
read:
    push edx
    push ecx
    mov ebx, eax
    mov eax, 0 ;默认为0，即正确且不为q
;从头开始解析，ecx作为偏移量
    mov ecx, 0
;判断第一个,如果不在0到9之间以及不是“-”，则可能是情况2,3
    cmp BYTE[ebx],45
    je .isNeg
    cmp BYTE[ebx],48
    jl .isqorinvalid
    cmp BYTE[ebx],57
    jg .isqorinvalid
.next:
;比对是否为+-*
    cmp BYTE[ebx], 43
    je .add
    cmp BYTE[ebx], 45
    je .neg
    cmp BYTE[ebx], 42
    je .mul
.isNeg:
;将字符一个个输入到first_string中
    mov dl,BYTE[ebx]
    mov BYTE[first_string+ecx],dl
    inc ecx
    inc ebx
    jmp .next

.second:
    inc ebx
    mov ecx, 0
.loop:
    cmp BYTE[ebx], 0
    je .rett
    mov dl,BYTE[ebx]
    mov BYTE[second_string+ecx],dl
    inc ecx
    inc ebx
    jmp .loop
.add:
    mov eax,3
    jmp .second
.neg:
    mov eax,4
    jmp .second
.mul:
    mov eax,5
    jmp .second

.isqorinvalid:
    cmp BYTE[ebx],113
    je .isq
    jmp .isvalid
.isq:
    mov eax,1
    jmp .rett
.isvalid:
    mov eax,2
    jmp .rett
.rett:
;去除second_string多余的换行
    push eax
    mov eax,second_string
    call strlen
    dec eax
    mov BYTE[second_string+eax], 0
    pop eax
    pop ecx
    pop edx
    ret


    

main:    
.loop:
    ;循环输入
    mov eax, input_string
    mov ebx, 255
    call getline		
    ;输入存储在input_string内部
    
    ;解析input_string 根据返回的ebx值对是否继续或输出invalid进行判断
    
    mov eax, input_string
    call read
    
    ;检测eax值
    cmp eax,1
    je .stop
    cmp eax,2
    je .invalid
    cmp eax,3
    je .myadd
    cmp eax,4
    ;je .mysub
    cmp eax,5
    je .mymul

.back:
    ;输出&清理内存
    mov eax, mid_result
    call puts
    mov eax, huanHang
    call puts
    call clearall
    jmp .loop

.stop:
    ret
.invalid:
    mov eax, invalid
    call puts
    jmp .back
.myadd:
    push ebx
    call getNum
    pop ebx
    call myadd
    jmp .back
.mymul:
    call getNum
;如果有乘数为0，则输出0
    cmp BYTE[first_num],48
    je .iszero
    cmp BYTE[second_num],48
    je .iszero
    call mymul
    jmp .back
.iszero:
    mov BYTE[mid_result],48
    jmp .back




;    ;利用加法实现乘法，让first_num自加（需要借助second_num和mid_result)，second_num赋值给third_num，并逐步减为0以此计数
;    mov eax, first_num 
;    mov ebx, mid_result
;    call cp
;    mov eax, second_num 
;    mov ebx, third_num
;    call cp
;    mov eax, first_num 
;    mov ebx, second_num
;    call cp
;    call mysub
;    call mysub
;.next:
;    mov eax, mid_result
;    mov ebx, first_num
;    call cp
;    call myadd
;    call mysub
;    cmp eax,1
;    je .back
;    jmp .next


;将eax的数据复制到ebx中
cp:
    push eax
    push ebx
    push ecx
    push edx
    mov ecx,eax;ecx持有eax的数据，eax用以计数
    mov eax,ebx
    call clear;清楚ebx的数据
    mov eax,ecx
    call strlen
.loop:
    dec eax
    mov dl, BYTE[ecx+eax]
    mov BYTE[ebx+eax], dl
    cmp eax,0
    jge .loop
    pop edx
    pop ecx
    pop ebx
    pop eax
    ret

signs:
    push eax
    mov eax,sign
    call puts
    pop eax
    ret

myadd:
    push eax
    push ebx
    push ecx
    push edx
    ;不断在mid_result上处理
    mov eax,first_num
    mov ebx,mid_result
    call cp
    ;first_len表示first_num的位数，second同理，
    ;first_len也作为计数器，让每个位依次加，second_len也作为计数器，在second加完后，使ebx一直为0
    mov eax, first_num
    call strlen
    mov WORD[first_len],ax
    mov eax, second_num
    call strlen
    mov WORD[second_len],ax
    mov ecx,0

.loop:
    mov eax,0
    mov ebx,0
    mov ax,WORD[first_len]
    cmp ax, 0
    je .done
    dec ax
    mov WORD[first_len],ax
    mov al,BYTE[first_num+eax]
    mov bx,WORD[second_len]
    cmp bx,0
    je .secondover
    dec bx
    mov WORD[second_len],bx
    mov bl,BYTE[second_num+ebx]
    jmp .go
    push eax
    pop eax
.secondover:
    mov ebx,48 ;char的0
    
.go:
    call sadd
    cmp ax, 0
    jl .done
    mov ax,WORD[first_len]
    mov BYTE[mid_result+eax],bl
    jmp .loop

.done:
;看是否出现9..+1的情况
    cmp ecx,0
    je .issmall
    mov eax,mid_result
    mov ebx,first_num
    call cp
    mov eax,first_num
    mov ebx,mid_result
    inc ebx
    call cp
    mov BYTE[mid_result],49
.issmall:
    pop edx
    pop ecx
    pop ebx
    pop eax    
    ret
;支持个位数加法，eax,ebx分别存储两个个位输入值char，ecx作为输入进位标识位；输出：ebx标识该位结果char，ecx标识是否进位
sadd:
    sub eax,48
    sub ebx,48
    add eax,ebx
    add eax,ecx
    mov ecx,0
    mov ebx,0
    cmp eax,10
    jl .isless
    sub eax,10
    mov ecx,1
.isless:
    mov ebx,eax
    add ebx,48
    ret

printmid:
     push eax
     mov eax,mid_result
     call puts
     mov eax,huanHang
     call puts
     pop eax
     ret
printfirst:
     push eax
     mov eax,huanHang
     call puts
     mov eax,first_num
     call puts
     pop eax
     ret
printsecond:
    push eax
     mov eax,huanHang
     call puts
     mov eax,second_num
     call puts
     pop eax
     ret

printthird:
     push eax
     mov eax,huanHang
     call puts
     mov eax,third_num
     call puts
     pop eax
     ret

;往前找，一直找到非0，然后将该位数-1，后面的位数全置为9
;如果找到偏移量为0的位数，且该数为0，则结束
;不断减小third_num
;mysub:
;    push ebx
;    mov eax, third_num
;    call strlen
;    dec eax     ;eax持有偏移量
;    mov ebx, eax
;.loop:
;    cmp BYTE[third_num+ebx], 48
;    jne .done       ;不需要往前推
;    cmp ebx, 0
;    je .over        ;second_num减为0
;    mov BYTE[third_num+ebx], 57
;    dec ebx
;    jmp .loop
;.done:
;    mov al, BYTE[third_num+ebx]
;    dec al
;    mov BYTE[third_num+ebx], al
;    mov eax,0   ;eax为0标识还可以继续减
;    pop ebx
;    ret
;.over:
;    mov eax,1   ;eax为1标识second_num为0
;    pop ebx
;    ret

;;该步骤是为了获取first_string与second_string的绝对值，并且按照长短分为first_num和second_num
getNum:
    push ebx
    mov eax, first_string
    call strlen
    mov ebx, eax
    mov eax, second_string
    call strlen
    cmp eax, ebx
    jl .notreverse
    mov eax, second_string
    mov ebx, first_num
    call cp
    mov eax, first_string
    mov ebx, second_num
    call cp
    jmp .over
.notreverse:
    mov eax, first_string 
    mov ebx, first_num
    call cp
    mov eax, second_string
    mov ebx, second_num
    call cp
.over:
    pop ebx
    ret

;将111*22化解为1110*2+111*2化解为1110+1110+111+111
;first_num一开始是111，而后变为1110，全部加到mid_result中
;为了与myadd兼容，进行以下映射first->second,second->third,mid_result->first
mymul:
    push eax
    push ebx
    push ecx
    ;先初始化mid_result,n+m个0
    mov eax, first_num
    call strlen
    mov ebx, eax
    mov eax, second_num
    call strlen
    add eax,ebx
.loop:
    mov BYTE[mid_result+eax],48
    dec eax
    cmp eax,0
    jge .loop
    ;third_num作为计数器
    mov eax,second_num
    mov ebx,third_num
    call cp
    call strlen
    mov ecx, eax;ecx作为位数指针
    dec ecx
    mov eax,first_num
    mov ebx,second_num
    call cp
    ;call printfirst
    ;call printsecond
    ;call printthird
.next:
    mov al,BYTE[third_num+ecx]
    cmp al,48
    je .ecxmove
    push eax
    mov eax,mid_result
    mov ebx,first_num
    call cp
    call myadd
    pop eax
    dec al
    mov BYTE[third_num+ecx],al
    jmp .next
.ecxmove:
    cmp ecx,0
    je .done
    dec ecx
    ;ecx前移，second_num就多一个0
    mov eax, second_num
    call strlen
    mov BYTE[second_num+eax],48
    jmp .next
.done:
    ;call printmid
    ;将多余的0去除
    mov ebx,0
    mov eax,0
.loopp:
    mov al, [mid_result+ebx]
    cmp al,48
    jne .looppdone
    inc ebx
    jmp .loopp
.looppdone:
    push ebx
    mov eax,mid_result
    mov ebx,first_num
    call cp
    pop ebx
    mov eax,first_num
    add eax,ebx    
    mov ebx,mid_result
    call cp
    pop ecx
    pop ebx
    pop eax

strlen:
    push ebx
    mov ebx, eax
.next:
    cmp BYTE[ebx], 0
    jz .finish
    inc ebx
    jmp .next
.finish:
    sub ebx, eax
    mov eax, ebx
    pop ebx
    ret

puts:
    push edx
    push ecx
    push ebx
    push eax

    mov ecx, eax
    call strlen
    mov edx, eax
    mov ebx, 1
    mov eax, 4
    int 80h

    pop eax
    pop ebx
    pop ecx
    pop edx
    ret

getline:
    push edx
    push ecx
    push ebx
    push eax

    mov edx, ebx
    mov ecx, eax
    mov ebx, 1
    mov eax, 3
    int 80h

    pop eax
    pop ebx
    pop ecx
    pop edx

    ret


    
